/**
 ******************************************************************************
 * 文件名          : bsp_can_core.c
 * 创建时间        : 2025.11.10
 * 作者            : Dayan
 ******************************************************************************
 *1. can 接口 核心入口模块
 * 2.本代码包含大量中文注释，请以UTF-8编码格式打开
 * 3.本代码最终解释权归哈尔滨工业大学（深圳）南工骁鹰战队Critical HIT所有
 *
 * Copyright (c) 哈尔滨工业大学（深圳）南工骁鹰战队Critical HIT 版权所有
 ******************************************************************************
 * 说明：
 ******************************************************************************
 */

#include "bsp_can_core.h"
#include <string.h>
#include <stdio.h>

// 静态变量
//static CAN_HandleTypeDef *hcan_ptr = &hcan2;
static bsp_can_msg_t tx_queue[CAN_TX_QUEUE_SIZE]; // 发送队列
static bsp_can_msg_t rx_queue[CAN_RX_QUEUE_SIZE]; // 接收队列

static volatile uint8_t tx_head = 0, tx_tail = 0, tx_count = 0; // 添加volatile
static volatile uint8_t rx_head = 0, rx_tail = 0, rx_count = 0; // 添加volatile
static bool initialized = false;
int8_t res_v = 0;

/**
 * @brief 初始化CAN驱动
 */
uint8_t BSP_CAN_Init(CAN_HandleTypeDef *hcan_pt)
{
    // 句柄检查
    if (hcan_pt == NULL)
    {
        return 1;
    }

    // 配置CAN过滤器（基础配置，接收所有消息）
   /* if (bsp_can_set_filter(hcan_pt, 1, 1) != HAL_OK)
    {
        return 2;
    }*/

    res_v = HAL_CAN_Start(hcan_pt);
    if (res_v != HAL_OK)
    {
        printf("CAN Start Error: %d\n", res_v);
        return 3;
    }

    // 使能接收中断
    if (HAL_CAN_ActivateNotification(hcan_pt, CAN_IT_RX_FIFO0_MSG_PENDING) != HAL_OK)
    {
        return 4;
    }

    // 初始化电机模块
    if (bsp_can_motor_init() != 0)
    {
        return 5;
    }

    initialized = true;
 
    return 0;
}

/**
 * @brief 主处理函数
 */
void BSP_CAN_Loop(CAN_HandleTypeDef *hcan_ptr)
{
    // 处理CAN核心功能（发送队列）
    bsp_can_core_process(hcan_ptr);

    // 处理电机数据
    bsp_can_motor_process();
}


/**
 * @brief 配置CAN过滤器
 */
uint8_t bsp_can_set_filter(CAN_HandleTypeDef *hcan_pt, uint16_t id, uint16_t mask)
{

    // 配置CAN过滤器（基础配置，接收所有消息）
    CAN_FilterTypeDef filter_config = {
        .FilterIdHigh = 0x0000,
        .FilterIdLow = 0x0000,
        .FilterMaskIdHigh = 0x0000,
        .FilterMaskIdLow = 0x0000,
        .FilterFIFOAssignment = CAN_RX_FIFO0,
        .FilterBank = 0,
        .FilterMode = CAN_FILTERMODE_IDMASK,
        .FilterScale = CAN_FILTERSCALE_32BIT,
        .FilterActivation = ENABLE};

    if (HAL_CAN_ConfigFilter(hcan_pt, &filter_config) != HAL_OK)
    {
        return 1;
    }

    return 0;
}

/**
 * @brief 发送CAN消息 将数据保存到tx_queue 队列
 */
uint8_t bsp_can_send(uint16_t id, const uint8_t *data, uint8_t len)
{
    if (!initialized)
    {
        return 1;
    }

    if (len > 8)
    {
        return 3; // 数据长度错误
    }

    if (tx_count >= CAN_TX_QUEUE_SIZE)
    {
        return 2; // 队列满
    }

    bsp_can_msg_t *msg = &tx_queue[tx_head];
    msg->id = id;
    msg->length = len;
    msg->timestamp = HAL_GetTick();

    if (data != NULL)
    {
        memcpy(msg->data, data, len);
    }
    else
    {
        memset(msg->data, 0, len); // 数据为空时清零
    }

    // 原子操作更新队列（简单场景下，中断不会修改tx_head）
    tx_head = (tx_head + 1) % CAN_TX_QUEUE_SIZE;
    tx_count++;

    return 0;
}

/**
 * @brief 处理发送队列
 */
void bsp_can_core_process(CAN_HandleTypeDef *hcan_ptr)
{
    if (!initialized)
    {
        return;
    }

    // 处理发送队列
    while (tx_count > 0 && HAL_CAN_GetTxMailboxesFreeLevel(hcan_ptr) > 0)
    {
        bsp_can_msg_t *msg = &tx_queue[tx_tail];

        CAN_TxHeaderTypeDef tx_header = {
            .StdId = msg->id,
            .ExtId = 0,
            .IDE = CAN_ID_STD,
            .RTR = CAN_RTR_DATA,
            .DLC = msg->length,
            .TransmitGlobalTime = DISABLE};

        uint32_t mailbox;
        HAL_StatusTypeDef result = HAL_CAN_AddTxMessage(hcan_ptr, &tx_header,
                                                        msg->data, &mailbox);

        if (result == HAL_OK)
        {
            // 发送成功，从队列移除
            tx_tail = (tx_tail + 1) % CAN_TX_QUEUE_SIZE;
            tx_count--;
        }
        else
        {
            // 发送失败，跳出循环等待下次重试
            break;
        }
    }
}

/**
 * @brief 接收消息
 */
uint8_t bsp_can_receive(bsp_can_msg_t *msg)
{
    if (!initialized || msg == NULL)
    {
        return 1;
    }

    if (rx_count == 0)
    {
        return 2; // 无消息
    }

    // 复制消息数据
    *msg = rx_queue[rx_tail];

    // 更新队列（简单场景下，中断不会修改rx_tail）
    rx_tail = (rx_tail + 1) % CAN_RX_QUEUE_SIZE;
    rx_count--;

    return 0;
}

/**
 * @brief 获取接收消息数量
 */
uint8_t bsp_can_available(void)
{
    return rx_count;
}

/**
 * @brief 清空接收队列
 */
void bsp_can_clear_rx_queue(void)
{
    rx_head = 0;
    rx_tail = 0;
    rx_count = 0;
}

/**
 * @brief 接收中断回调
 */
void bsp_can_rx_callback(CAN_HandleTypeDef *hcan_ptr)
{
    if (!initialized)
    {
        return;
    }

    CAN_RxHeaderTypeDef rx_header;
    uint8_t data[8];
    uint32_t current_timestamp = HAL_GetTick();

    while (HAL_CAN_GetRxFifoFillLevel(hcan_ptr, CAN_RX_FIFO0) > 0)
    {
        if (HAL_CAN_GetRxMessage(hcan_ptr, CAN_RX_FIFO0, &rx_header, data) != HAL_OK)
        {
            continue; // 读取失败，继续处理下一条消息
        }

        // 检查队列是否已满
        if (rx_count >= CAN_RX_QUEUE_SIZE)
        {
            return; // 队列满，直接返回
        }

        // 只处理标准帧
        if (rx_header.IDE != CAN_ID_STD)
        {
            continue;
        }

        // 存储消息到队列
        bsp_can_msg_t *msg = &rx_queue[rx_head];
        msg->id = rx_header.StdId;
        msg->length = rx_header.DLC;
        msg->timestamp = current_timestamp;

        // 安全的数据拷贝
        uint8_t copy_length = (rx_header.DLC <= 8) ? rx_header.DLC : 8;
        if (copy_length > 0)
        {
            memcpy(msg->data, data, copy_length);
        }

        // 填充剩余数据区域（可选）
        if (copy_length < 8)
        {
            memset(&msg->data[copy_length], 0, 8 - copy_length);
        }

        // 更新队列指针和计数
        rx_head = (rx_head + 1) % CAN_RX_QUEUE_SIZE;
        rx_count++;
    }
}

// CAN接收中断回调
// CAN接收中断回调为了调试，开启CAN1 CAN2
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
    printf("bsp_can_rx_callback\n");
    if (hcan->Instance == CAN1)
    {
        bsp_can_rx_callback(hcan);
    }

    if (hcan->Instance == CAN2)
    {
        bsp_can_rx_callback(hcan);
    }
}